﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Data;
using System.Data.Linq;
using System.Web.UI.WebControls;
using Emporium_Web.Enums;
using Emporium_Web.DBML;

namespace Emporium_Web
{
    public partial class ClienteForm : System.Web.UI.Page
    {
        /// <summary>
        /// Es el código de cliente
        /// </summary>
        private int ClienteId
        {
            get { return ViewState["RequestCodeClient"] == null ? -1 : (int)ViewState["RequestCodeClient"]; }
            set { ViewState["RequestCodeClient"] = value; }
        }

        /// <summary>
        /// Contiene la operación que se realizará en el formulario
        /// </summary>
        private AccionesForm Operacion
        {
            get { return ViewState["Operation"] == null ? AccionesForm.Consultar : (AccionesForm)ViewState["Operation"]; }
            set { ViewState["Operation"] = value; }
        }

        /// <summary>
        /// Las direcciones del cliente.
        /// </summary>
        private List<Direccion> Direcciones
        {
            get
            {
                return ViewState["TG_ClienteDirecciones"] == null ? null : (List<Direccion>)ViewState["TG_ClienteDirecciones"];
            }
            set
            {
                ViewState["TG_ClienteDirecciones"] = value;
            }
        }

        /// <summary>
        /// Las direcciones que se le agregan al cliente.
        /// </summary>
        private List<Direccion> DireccionesNuevas
        {
            get
            {
                return ViewState["TG_DireccionesNuevas"] == null ? null : (List<Direccion>)ViewState["TG_DireccionesNuevas"];
            }
            set
            {
                ViewState["TG_DireccionesNuevas"] = value;
            }
        }

        /// <summary>
        /// Las direcciones que se eliminan del cliente.
        /// </summary>
        private List<int> DireccionesEliminadas
        {
            get
            {
                return ViewState["TG_DireccionesEliminadas"] == null ? null : (List<int>)ViewState["TG_DireccionesEliminadas"];
            }
            set
            {
                ViewState["TG_DireccionesEliminadas"] = value;
            }
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            try
            {
                if (!IsPostBack)
                {
                    errorMessage.Visible = false;

                    Master.ActualizaMenu(MenuPrincipal.Generales, (int)MenuGenerales.Cliente);

                    Master.AgregarBreadcrumb("Clientes", "#", true);
                    Master.AgregarBreadcrumb("Listado", "ClienteList.aspx", false);

                    int clienteId = 0;

                    if (Request.QueryString["ClienteId"] != null && Int32.TryParse(Request.QueryString["ClienteId"], out clienteId))
                    {
                        this.ClienteId = clienteId;
                    }
                    else
                    {
                        this.ClienteId = -1;
                    }

                    EstablecerComportamiento();

                }
            }
            catch (Exception x)
            {
                lblErrorMessage.Text = x.Message;
                errorMessage.Visible = true;
            }
        }

        protected void btnGrabar_Click(object sender, EventArgs e)
        {
            try
            {
                Grabar();
                Response.Redirect("ClienteList.aspx");
            }
            catch (Exception x)
            {
                lblErrorMessage.Text = x.Message;
                errorMessage.Visible = true;
            }
        }

        protected void btnAtras_Click(object sender, EventArgs e)
        {
            Response.Redirect("ClienteList.aspx");
        }

        protected void gvDirecciones_RowCommand(object sender, GridViewCommandEventArgs e)
        {
            try
            {
                if (e.CommandName.Equals("Insert"))
                {
                    AgregarDireccion();
                }
                else if (e.CommandName.Equals("Remove"))
                {
                    EliminarDireccion(e.CommandArgument.ToString());
                }

                ListarDirecciones();
            }
            catch (Exception x)
            {
                lblErrorMessage.Text = x.Message;
                errorMessage.Visible = true;
            }
        }

        /// <summary>
        /// Llena los mensajes de error de las validaciones del formulario.
        /// </summary>
        private void EstablecerValidaciones()
        {
            reqNombre.ErrorMessage = Resources.MensajesValidacion.RequiredField;
            reqNumero.ErrorMessage = Resources.MensajesValidacion.RequiredField;
            regexEmailValid.ErrorMessage = Resources.MensajesValidacion.InvalidEmail;
            regexFax.ErrorMessage = Resources.MensajesValidacion.OnlyNumbers;
            regexTelefono.ErrorMessage = Resources.MensajesValidacion.OnlyNumbers;
            regexMovil.ErrorMessage = Resources.MensajesValidacion.OnlyNumbers;

            if (gvDirecciones.FooterRow != null)
            {
                RequiredFieldValidator reqDireccion = (RequiredFieldValidator)gvDirecciones.FooterRow.FindControl("reqDireccion");
                reqDireccion.Text = Resources.MensajesValidacion.RequiredField;
            }
        }

        /// <summary>
        /// Prepara el formulario para la operación que se haya elegido (Agregar, Modificar o Consultar)
        /// </summary>
        private void EstablecerComportamiento()
        {
            int accion = 0;

            if (Request.QueryString["Operacion"] != null && Int32.TryParse(Request.QueryString["Operacion"].ToString(), out accion))
            {
                switch (accion)
                {
                    case (int)AccionesForm.Consultar:
                        this.Operacion = AccionesForm.Consultar;
                        leyendaForm.Text = Resources.Leyendas.FormConsultar;
                        Master.AgregarBreadcrumb("Consultar", "#", false);
                        LlenarDatosForm();
                        ListarDirecciones();
                        #region Inhabilita controles
                        rbExtranjero.Enabled = false;
                        rbNacional.Enabled = false;
                        txtNombre.Enabled = false;
                        txtNumero.Enabled = false;
                        lstTipo.Enabled = false;
                        txtEmail.Enabled = false;
                        txtTelefono.Enabled = false;
                        txtFax.Enabled = false;
                        txtMovil.Enabled = false;
                        txtContacto.Enabled = false;
                        txtWeb.Enabled = false;
                        btnGrabar.Visible = false;
                        #endregion
                        break;
                    case (int)AccionesForm.Modificar:
                        this.Operacion = AccionesForm.Modificar;
                        leyendaForm.Text = Resources.Leyendas.FormModificar;
                        Master.AgregarBreadcrumb("Modificar", "#", false);
                        LlenarDatosForm();
                        ListarDirecciones();
                        EstablecerValidaciones();
                        break;
                    default:
                        this.Operacion = AccionesForm.Adicionar;
                        leyendaForm.Text = Resources.Leyendas.FormAdicionar;
                        Master.AgregarBreadcrumb("Adicionar", "#", false);
                        ListarDirecciones();
                        EstablecerValidaciones();
                        break;
                }
            }
            else
            {
                this.Operacion = AccionesForm.Adicionar;
                leyendaForm.Text = Resources.Leyendas.FormAdicionar;
                Master.AgregarBreadcrumb("Adicionar", "#", false);
                ListarDirecciones();
                EstablecerValidaciones();
            }

        }

        /// <summary>
        /// Llena los datos del formulario con la información del cliente.
        /// </summary>
        /// <param name="clienteId">Identificador del cliente.</param>
        private void LlenarDatosForm()
        {
            TablasDataContext database = new TablasDataContext();

            var cliente = (from clientes in database.TG_Cliente
                           where clientes.Id == this.ClienteId
                           select clientes).First();

            if (cliente != null)
            {
                txtNombre.Text = cliente.Nombre;
                txtNumero.Text = cliente.Numero;
                txtTelefono.Text = cliente.Telefono;
                txtWeb.Text = cliente.Web;
                txtContacto.Text = cliente.Contacto;
                txtEmail.Text = cliente.Email;
                txtFax.Text = cliente.Fax;
                txtMovil.Text = cliente.Movil;
                lstTipo.SelectedValue = cliente.Tipo.ToString();
                rbNacional.Checked = cliente.Origen == 'N';
                rbExtranjero.Checked = cliente.Origen == 'E';

                if (this.Direcciones == null)
                {
                    this.Direcciones = new List<Direccion>();
                }

                for (int i = 0; i < cliente.TG_ClienteDireccion.Count; i++)
                {
                    TG_ClienteDireccion tg_direccion = cliente.TG_ClienteDireccion[i];

                    this.Direcciones.Add(new Direccion
                    {
                        Id = tg_direccion.Id,
                        ClienteId = tg_direccion.ClienteId,
                        Descripcion = tg_direccion.Descripcion,
                        PaisId = tg_direccion.PaisId,
                        Pais = tg_direccion.TG_Pais.Descripcion,
                        Referencia = tg_direccion.Referencia,
                    });
                }
            }
            else
            {
                errorMessage.Visible = true;
                lblErrorMessage.Text = Resources.MensajesValidacion.NoDataFound;
            }
        }

        /// <summary>
        /// Llena el grid de direcciones.
        /// </summary>
        private void ListarDirecciones()
        {
            if (this.Direcciones == null)
            {
                this.Direcciones = new List<Direccion>();
            }

            gvDirecciones.ShowFooter = this.Operacion != AccionesForm.Consultar;
            gvDirecciones.Columns[3].Visible = this.Operacion != AccionesForm.Consultar;

            if (this.Direcciones.Count > 0)
            {
                gvDirecciones.DataSource = this.Direcciones;
                gvDirecciones.DataBind();
                gvDirecciones.UseAccessibleHeader = false;
                gvDirecciones.HeaderRow.TableSection = TableRowSection.TableHeader;
                ListarPaises();
            }
            else if (this.Operacion != AccionesForm.Consultar)
            {
                AgregarFilaVacia();
                LinkButton lnkEliminar = (LinkButton)gvDirecciones.Rows[0].FindControl("lnkEliminar");
                lnkEliminar.Visible = false;
                ListarPaises();
            }
            else
            {
                lblDirecciones.Visible = false;
                ulMensajeGridFooter.Visible = false;
            }

             
            lblMensajeGridFooter.Text = String.Format(Resources.MensajesValidacion.GridFooterMessage, this.Direcciones.Count);
        }

        /// <summary>
        /// Llena la lista de países en el grid de direcciones.
        /// </summary>
        private void ListarPaises()
        {
            TablasDataContext database = new TablasDataContext();

            var listarQuery = from paises in database.TG_Pais
                              orderby paises.Descripcion
                              select paises;

            DropDownList dllPaises = ((DropDownList)gvDirecciones.FooterRow.FindControl("ddlPais"));
            dllPaises.DataSource = listarQuery.ToList();
            dllPaises.DataBind();
        }

        /// <summary>
        /// Agrega una fila vacía al grid de direcciones.
        /// </summary>
        /// <param name="gv"></param>
        private void AgregarFilaVacia()
        {
            DataTable source = new DataTable();

            source.Columns.Add("Id");
            
            source.Columns.Add("Descripcion");
            source.Columns.Add("Referencia");
            source.Columns.Add("Pais");

            source.Rows.Add(source.NewRow());

            gvDirecciones.DataSource = source;
            gvDirecciones.DataBind();
        }

        private void EliminarDireccion(string direccionSeleccionada)
        {
            if (this.DireccionesEliminadas == null)
            {
                this.DireccionesEliminadas = new List<int>();
            }

            int direccionId = 0;

            if (Int32.TryParse(direccionSeleccionada, out direccionId))
            {
                this.DireccionesEliminadas.Add(direccionId);
                this.Direcciones = EliminaDireccionDeLista(direccionId, this.Direcciones);
                this.DireccionesNuevas = EliminaDireccionDeLista(direccionId, this.DireccionesNuevas);
            }
        }

        private void AgregarDireccion()
        {
            TextBox txtDescripcion = (TextBox)gvDirecciones.FooterRow.FindControl("txtDescripcion");
            DropDownList ddlPais = (DropDownList)gvDirecciones.FooterRow.FindControl("ddlPais");
            TextBox txtReferencia = (TextBox)gvDirecciones.FooterRow.FindControl("txtReferencia");

            if (this.DireccionesNuevas == null)
            {
                this.DireccionesNuevas = new List<Direccion>();
            }

            Direccion nuevaDireccion = new Direccion
            {
                ClienteId = this.ClienteId,
                Descripcion = txtDescripcion.Text,
                PaisId = Convert.ToInt32(ddlPais.SelectedValue),
                Pais = ddlPais.SelectedItem.Text,
                Referencia = txtReferencia.Text
            };

            this.DireccionesNuevas.Add(nuevaDireccion);
            this.Direcciones.Add(nuevaDireccion);
        }

        private List<Direccion> EliminaDireccionDeLista(int direccionId, List<Direccion> direcciones)
        {

            if (direcciones == null)
            {
                return null;
            }

            List<Direccion> tempDirecciones = new List<Direccion>();

            for (int i = 0; i < direcciones.Count; i++)
            {
                if (direcciones[i].Id != direccionId)
                {
                    tempDirecciones.Add(direcciones[i]);
                }
            }

            return tempDirecciones;
        }

        private void Grabar()
        {
            switch (this.Operacion)
            {
                case AccionesForm.Adicionar:
                    Insertar();
                    break;
                case AccionesForm.Modificar:
                    Actualizar();
                    break;
                default:
                    lblErrorMessage.Text = Resources.MensajesValidacion.InvalidOperation;
                    errorMessage.Visible = true;
                    break;
            }
        }

        private void Actualizar()
        {
            TablasDataContext database = new TablasDataContext();

            TG_Cliente cliente = (from clientes in database.TG_Cliente
                                  where clientes.Id == this.ClienteId
                                  select clientes).First();

            cliente.Nombre = txtNombre.Text;
            cliente.Contacto = txtContacto.Text;
            cliente.Email = txtEmail.Text;
            cliente.Fax = txtFax.Text;
            cliente.Movil = txtMovil.Text;
            cliente.Numero = txtNumero.Text;
            cliente.Telefono = txtTelefono.Text;
            cliente.Tipo = lstTipo.SelectedValue[0];
            cliente.Web = txtWeb.Text;
            cliente.Origen = rbExtranjero.Checked ? 'E' : 'N';

            if (this.DireccionesNuevas != null)
            {
                for (int i = 0; i < this.DireccionesNuevas.Count; i++)
                {
                    cliente.TG_ClienteDireccion.Add(new TG_ClienteDireccion
                    {
                        ClienteId = this.ClienteId,
                        Descripcion = this.DireccionesNuevas[i].Descripcion,
                        PaisId = this.DireccionesNuevas[i].PaisId,
                        Referencia = this.DireccionesNuevas[i].Referencia,
                    });
                }
            }

            if (this.DireccionesEliminadas != null)
            {
                for (int i = 0; i < this.DireccionesEliminadas.Count; i++)
                {
                    foreach (TG_ClienteDireccion item in cliente.TG_ClienteDireccion)
                    {
                        if (item.Id == this.DireccionesEliminadas[i])
                        {
                            database.TG_ClienteDireccion.DeleteOnSubmit(item);
                        }
                    }
                }
            }

            database.SubmitChanges();
        }

        private void Insertar()
        {
            TablasDataContext database = new TablasDataContext();

            TG_Cliente cliente = new TG_Cliente
            {
                Nombre = txtNombre.Text,
                Contacto = txtContacto.Text,
                Email = txtEmail.Text,
                Fax = txtFax.Text,
                Movil = txtMovil.Text,
                Numero = txtNumero.Text,
                Telefono = txtTelefono.Text,
                Tipo = lstTipo.SelectedValue[0],
                Web = txtWeb.Text,
                Origen = rbExtranjero.Checked ? 'E' : 'N'
            };

            cliente.TG_ClienteDireccion = new EntitySet<TG_ClienteDireccion>();

            if (this.Direcciones != null)
            {
                for (int i = 0; i < this.Direcciones.Count; i++)
                {
                    cliente.TG_ClienteDireccion.Add(new TG_ClienteDireccion
                    {
                        ClienteId = this.Direcciones[i].ClienteId,
                        Descripcion = this.Direcciones[i].Descripcion,
                        PaisId = this.Direcciones[i].PaisId,
                        Referencia = this.Direcciones[i].Referencia,
                    });
                }
            }

            database.TG_Cliente.InsertOnSubmit(cliente);
            database.SubmitChanges();
        }
    }

    [Serializable]
    class Direccion
    {
        public int Id { get; set; }
        public int ClienteId { get; set; }
        public string Descripcion { get; set; }
        public string Referencia { get; set; }
        public int PaisId { get; set; }
        public string Pais { get; set; }
    }

}